/*
 * Copyright 2007-2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.paoding.rose.web.instruction;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.paoding.rose.impl.util.SpringUtils;
import net.paoding.rose.web.Invocation;
import net.paoding.rose.web.impl.view.RoseViewResolver;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;

/**
 * 
 * @author zhiliang.wang [qieqie.wang@paoding.net]
 * 
 */
public class ViewInstruction extends AbstractInstruction {

	@Override
	public void doRender(Invocation invocation)	throws Exception {
		String name = resolvePlaceHolder(this.name, invocation);
		String encoding = resolvePlaceHolder(this.encoding, invocation);
		String contentType = resolvePlaceHolder(this.contentType, invocation);
		
		HttpServletRequest request = invocation.getRequest();
		HttpServletResponse response = invocation.getResponse();
		if (contentType != null) {
			response.setContentType(contentType);
		}
		if (encoding != null) {
			response.setCharacterEncoding(encoding);
		}
		ViewResolver viewResolver = getRoseViewResolver(invocation);
		View view = viewResolver.resolveViewName(name, request.getLocale());
		view.render(invocation.getModel().getAttributes(), request, response);
	}
	
	//-------------------------------------------
	
	// 视图名称
	private String name;

	// 非空时，设置该页面的内容格式
	private String contentType;

	// 非空时，设置该页面的编码格式
	private String encoding;
	
	private String viewResolverBeanName = "roseViewResolver";
	

	protected ViewResolver getRoseViewResolver(Invocation invocation) {
		ViewResolver roseViewResolver = (ViewResolver) SpringUtils.getBean(
				invocation.getApplicationContext(), viewResolverBeanName);
		if (roseViewResolver == null) {
			roseViewResolver = registerRoseViewResolver(invocation.getApplicationContext());
		}
		return roseViewResolver;
	}

	public ViewInstruction contentType(String contentType) {
		setContentType(contentType);
		return this;
	}

	public ViewInstruction encoding(String encoding) {
		setEncoding(encoding);
		return this;
	}

	public ViewInstruction name(String name) {
		setName(name);
		return this;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}

	public String encoding() {
		return encoding;
	}

	public String contentType() {
		return contentType;
	}

	/**
	 * 注册一个 {@link RoseViewResolver}定义到上下文中，以被这个类的所有实例使用
	 * 
	 * @return
	 */
	protected RoseViewResolver registerRoseViewResolver(WebApplicationContext applicationContext) {
		// 并发下，重复注册虽然不会错误，但没有必要重复注册
		synchronized (applicationContext) {
			if (SpringUtils.getBean(applicationContext, viewResolverBeanName) == null) {
				GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
				beanDefinition.setBeanClass(RoseViewResolver.class);
				((BeanDefinitionRegistry) applicationContext.getAutowireCapableBeanFactory())
					.registerBeanDefinition(viewResolverBeanName, beanDefinition);
				if (logger.isDebugEnabled()) {
					logger.debug("registered bean definition:"
							+ RoseViewResolver.class.getName());
				}
			}
			return (RoseViewResolver) SpringUtils.getBean(
					applicationContext, viewResolverBeanName);
		}
	}
}
